<?php
namespace libs\qoy\Cache;
use libs\qoy\Exception\ExceptionInternalServerError;
/**
 * Redis Redis缓存
 * @param array $config 初始化配置
 * @param string $config['type']    Redis连接方式 unix,http
 * @param string $config['socket']  unix方式连接时，需要配置
 * @param string $config['host']    Redis域名
 * @param int    $config['port']    Redis端口,默认为6379
 * @param string $config['prefix']  Redis key prefix
 * @param string $config['auth']    Redis 身份验证
 * @param int    $config['db']      Redis库,默认0
 * @param int    $config['timeout'] 连接超时时间,单位秒,默认300
 * @throws ExceptionInternalServerErro
 */

class CacheRedis implements ICache {

    protected $redis;

    protected $auth;

    protected $prefix;

    /**
     * 构造方法
     * @param array $config 初始化配置
     * @param string $config['type']    Redis连接方式 unix,http
     * @param string $config['socket']  unix方式连接时，需要配置
     * @param string $config['host']    Redis域名
     * @param int    $config['port']    Redis端口,默认为6379
     * @param string $config['prefix']  Redis key prefix
     * @param string $config['auth']    Redis 身份验证
     * @param int    $config['db']      Redis库,默认0
     * @param int    $config['timeout'] 连接超时时间,单位秒,默认300
     * @throws ExceptionInternalServerErro
     */
    public function __construct(array $config) {
        $this->redis = new Redis();

        // 连接
        if (isset($config['type']) && $config['type'] == 'unix') {
            if (!isset($config['socket'])) {
                throw new ExceptionInternalServerError(ExceptionInternalServerError::CONFIG_ERRER);
            }
            $this->redis->connect($config['socket']);
        } else {
            $port = isset($config['port']) ? intval($config['port']) : 6379;
            $timeout = isset($config['timeout']) ? intval($config['timeout']) : 300;
            $this->redis->connect($config['host'], $port, $timeout);
        }

        // 验证
        $this->auth = isset($config['auth']) ? $config['auth'] : '';
        if ($this->auth != '') {
            $this->redis->auth($this->auth);
        }

        // 选择
        $dbIndex = isset($config['db']) ? intval($config['db']) : 0;
        $this->redis->select($dbIndex);

        $this->prefix = isset($config['prefix']) ? $config['prefix'] : 'phalapi:';
    }

    /**
     * @see ICache->set
     */
    public function set(string $key, $value,int $expire = 600) {
        $this->redis->setex($this->formatKey($key), $expire, $this->formatValue($value));
    }
    /**
     * @see ICache->get
     */
    public function get(string $key) {
        $value = $this->redis->get($this->formatKey($key));
        return $value !== FALSE ? $this->unformatValue($value) : NULL;
    }
    /**
     * @see ICache->delete
     */
    public function delete(string $key) {
        return $this->redis->delete($this->formatKey($key));
    }

    /**
     * 检测是否存在key,若不存在则赋值value
     * @param string $key 缓存key
     * @param mixed $value 缓存的内容
     * @return mixed 缓存的内容
     */
    public function setnx(string $key, $value) {
        return $this->redis->setnx($this->formatKey($key), $this->formatValue($value));
    }

    public function lPush(string $key, $value) {
        return $this->redis->lPush($this->formatKey($key), $this->formatValue($value));
    }

    public function rPush(string $key, $value) {
        return $this->redis->rPush($this->formatKey($key), $this->formatValue($value));
    }

    public function lPop(string $key) {
        $value = $this->redis->lPop($this->formatKey($key));
        return $value !== FALSE ? $this->unformatValue($value) : NULL;
    }

    public function rPop(string $key) {
        $value = $this->redis->rPop($this->formatKey($key));
        return $value !== FALSE ? $this->unformatValue($value) : NULL;
    }

    protected function formatKey(string $key) {
        return $this->prefix . $key;
    }

    protected function formatValue($value) {
        return @serialize($value);
    }

    protected function unformatValue($value) {
        return @unserialize($value);
    }
}
